package com.smartum.mpr.services;

import java.util.List;

import org.codehaus.jackson.JsonNode;
import org.codehaus.jackson.map.ObjectMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

import com.smartum.mpr.business.JobBusiness;
import com.smartum.mpr.business.StaticDataBusiness;
import com.smartum.mpr.business.UserBusiness;
import com.smartum.mpr.exception.NotExistsItemException;
import com.smartum.mpr.exception.NotExistsJobException;
import com.smartum.mpr.exception.NotExistsSubCategoryException;
import com.smartum.mpr.exception.NotExistsUserException;
import com.smartum.mpr.model.Item;
import com.smartum.mpr.model.ItemImage;
import com.smartum.mpr.model.ItemType;
import com.smartum.mpr.model.Job;
import com.smartum.mpr.model.JobSubCategory;
import com.smartum.mpr.model.User;
import com.smartum.mpr.store.local.ItemImageProvider;
import com.smartum.mpr.validators.EmailValidator;

@Controller
@RequestMapping("/job")
public class JobService extends BaseService<Job> {

	private static final String JOB_CATEGORY_ID_PROPERTY = "job_category_id";
	private static final String JOB_ID_PROPERTY = "job_id";
	private static final String JOB_PRICE_PROPERTY = "job_price";
	private static final String JOB_TITLE_PROPERTY = "job_title";
	private static final String JOB_DESCRIPTION_PROPERTY = "job_description";
	private static final String JOB_PHONE_NUMBER_PROPERTY = "job_phone_number";
	private static final String JOB_SUBCATEGORY_ID_PROPERTY = "job_subcategory_id";
	private static final String JOB_COUNTY_ID_PROPERTY = "job_county_id";
	private static final String JOB_EMAIL_PROPERTY = "job_email";
	@Autowired
	private JobBusiness jobBusiness;
	@Autowired
	private UserBusiness userBusiness;
	@Autowired
	private StaticDataBusiness staticDataBusiness;

	@RequestMapping(method = RequestMethod.POST, value = "/search")
	public ResponseEntity<String> searchJobs(@RequestBody String json) {
		LOGGER_API.info("request: get search: " + json);
		try {
			checkRequestPermissions(json);

			String request = extractRequestStringData(json);
			ObjectMapper mapper = getTargetParser().getMapper();
			JsonNode requestNode = mapper.readTree(request);
			Long timestamp = requestNode.get(TIMESTAMP_PROPERTY).asLong();
			int amount = requestNode.get(AMOUNT_PROPERTY).asInt();

			Long categoryId = null;
			Long subCategoryId = null;
			Long countyId = null;
			String priceSorting = null;

			if (requestNode.get(JOB_CATEGORY_ID_PROPERTY) != null) {
				categoryId = requestNode.get(JOB_CATEGORY_ID_PROPERTY).asLong();
			}

			if (requestNode.get(JOB_SUBCATEGORY_ID_PROPERTY) != null) {
				subCategoryId = requestNode.get(JOB_SUBCATEGORY_ID_PROPERTY).asLong();
			}

			if (requestNode.get(JOB_PRICE_PROPERTY) != null) {
				priceSorting = requestNode.get(JOB_PRICE_PROPERTY).asText();
			}

			if (requestNode.get(JOB_COUNTY_ID_PROPERTY) != null) {
				countyId = requestNode.get(JOB_COUNTY_ID_PROPERTY).asLong();
			}

			Boolean getHeighest = null;

			if (priceSorting != null) {

				if (priceSorting.equals("heighest")) {
					getHeighest = true;
				} else if (priceSorting.equals("lowest")) {
					getHeighest = false;
				}

			}
			ResponseEntity<String> response = getResponseInJsonType(
			        generateSuccessJson(getTargetParser()
			                .writeEntityList(
			                        jobBusiness.searchJobs(categoryId, subCategoryId, getHeighest, timestamp, amount,
			                                countyId))), HttpStatus.OK);

			LOGGER_API.info("response: search job - ok ");
			logResponse(response);
			return response;
		} catch (Exception e) {
			LOGGER_API.error("response: search job", e);
			return handleException(e);
		}
	}

	@RequestMapping(method = RequestMethod.POST, value = "/get/user")
	public ResponseEntity<String> getUserJobs(@RequestBody String json) {
		LOGGER_API.info("request: get user jobs: " + json);
		try {
			String request = extractRequestStringData(json);
			ObjectMapper mapper = getTargetParser().getMapper();
			JsonNode requestNode = mapper.readTree(request);
			Long timestamp = requestNode.get(TIMESTAMP_PROPERTY).asLong();
			int amount = requestNode.get(AMOUNT_PROPERTY).asInt();

			User user = null;

			if (requestNode.get("user_id") == null) {
				String token = extractTokenStringData(json);
				user = userBusiness.getUserByToken(token);
			} else {
				checkRequestPermissions(json);
				long userId = requestNode.get("user_id").asLong();
				user = userBusiness.getById(userId);
			}

			if (user == null) {
				throw new NotExistsUserException();
			}

			List<Job> jobs = jobBusiness.getUserJobs(timestamp, amount, user.getId());
			ResponseEntity<String> response = getResponseInJsonType(generateSuccessJson(getTargetParser()
			        .writeEntityList(jobs)), HttpStatus.OK);
			LOGGER_API.info("response: get user job: ");
			logResponse(response);
			return response;
		} catch (Exception e) {
			LOGGER_API.error("response: get user job", e);
			return handleException(e);
		}
	}

	@RequestMapping(method = RequestMethod.POST, value = "/get/one")
	public ResponseEntity<String> getOneJobById(@RequestBody String json) {
		LOGGER_API.info("request: get user jobs: " + json);
		try {
			checkRequestPermissions(json);
			String request = extractRequestStringData(json);
			ObjectMapper mapper = getTargetParser().getMapper();
			JsonNode requestNode = mapper.readTree(request);
			Long jobId = requestNode.get(JOB_ID_PROPERTY).asLong();
			Job job = jobBusiness.getJobById(jobId);
			ResponseEntity<String> response;
			if (job == null) {
				throw new NotExistsJobException("with id:" + jobId);
			}
			response = getResponseInJsonType(generateSuccessJson(getTargetParser().writeEntity(job)), HttpStatus.OK);
			LOGGER_API.info("response: get user job: ");
			logResponse(response);
			return response;
		} catch (Exception e) {
			LOGGER_API.error("response: get user job", e);
			return handleException(e);
		}
	}

	@RequestMapping(method = RequestMethod.POST, value = "/delete")
	public ResponseEntity<String> deleteJob(@RequestBody String json) {
		LOGGER_API.info("request: delete job: " + json);
		try {
			String token = extractTokenStringData(json);
			userBusiness.getUserByToken(token);

			String request = extractRequestStringData(json);
			ObjectMapper mapper = getTargetParser().getMapper();
			JsonNode requestNode = mapper.readTree(request);
			Long jobId = requestNode.get(JOB_ID_PROPERTY).asLong();
			Job job = jobBusiness.getJobById(jobId);
			if (job == null) {
				throw new NotExistsJobException("with id: " + jobId);
			}

			jobBusiness.deleteJob(jobId);
			LOGGER_API.info("response: delete job - OK");
			return new ResponseEntity<String>(HttpStatus.OK);
		} catch (Exception e) {
			LOGGER_API.error("response: delete job", e);
			return handleException(e);
		}
	}

	@RequestMapping(method = RequestMethod.POST, value = "/post")
	public ResponseEntity<String> postJob(@RequestBody String json) {
		LOGGER_API.info("request: post job: " + json);
		try {
			String token = extractTokenStringData(json);
			String request = extractRequestStringData(json);

			User owner = userBusiness.getUserByToken(token);

			
			ObjectMapper mapper = getTargetParser().getMapper();
			JsonNode requestNode = mapper.readTree(request);

			Double jobPrice = requestNode.get(JOB_PRICE_PROPERTY).asDouble();
			String jobTitle = requestNode.get(JOB_TITLE_PROPERTY).asText();
			String jobDescription = requestNode.get(JOB_DESCRIPTION_PROPERTY).asText();
			String jobPhoneNumber = requestNode.get(JOB_PHONE_NUMBER_PROPERTY).asText();
			Long jobSubCategoryId = requestNode.get(JOB_SUBCATEGORY_ID_PROPERTY).asLong();
			Long jobCountyId = requestNode.get(JOB_COUNTY_ID_PROPERTY).asLong();
			String jobEmail = requestNode.get(JOB_EMAIL_PROPERTY).asText();

			new EmailValidator().validate(jobEmail);
			
			JobSubCategory subCategory  = staticDataBusiness.getJobSubCategoryById(jobSubCategoryId);
			if(subCategory==null){
				throw new NotExistsSubCategoryException();
			}
			
			jobBusiness.checkPostPermission(owner.getId(), subCategory.getCategory().getId());

			Job job = new Job();
			job.setSubCategory(staticDataBusiness.getJobSubCategoryById(jobSubCategoryId));
			job.setCounty(staticDataBusiness.getCountyById(jobCountyId));
			job.setPrice(jobPrice);
			job.setDescription(jobDescription);
			job.setPhoneNumber(jobPhoneNumber);
			job.setTitle(jobTitle);
			job.setOwner(owner);
			job.setTimeStamp(System.currentTimeMillis());
			job.setEmail(jobEmail);

			jobBusiness.saveJob(job);
			
			jobBusiness.removePostPermission(owner.getId(), subCategory.getCategory().getId());
			
			ResponseEntity<String> response = getResponseInJsonType(
			        generateSuccessJson(getTargetParser().writeEntity(job)), HttpStatus.OK);
			LOGGER_API.info("response: post job - OK");
			logResponse(response);

			return response;
		} catch (Exception e) {
			LOGGER_API.error("response: post job", e);
			return handleException(e);
		}
	}

	@RequestMapping(method = RequestMethod.POST, value = "/update")
	public ResponseEntity<String> updateJob(@RequestBody String json) {
		LOGGER_API.info("request: update job: " + json);
		try {
			String token = extractTokenStringData(json);
			String request = extractRequestStringData(json);
			ObjectMapper mapper = getTargetParser().getMapper();

			User owner = userBusiness.getUserByToken(token);

			JsonNode requestNode = mapper.readTree(request);

			Long jobId = requestNode.get(JOB_ID_PROPERTY).asLong();

			Job job = jobBusiness.getJobById(jobId);

			if (job == null) {
				throw new NotExistsJobException("with id: " + jobId);
			}

			if (requestNode.get(JOB_PRICE_PROPERTY) != null) {
				job.setPrice(requestNode.get(JOB_PRICE_PROPERTY).asDouble());
			}
			if (requestNode.get(JOB_TITLE_PROPERTY) != null) {
				job.setTitle(requestNode.get(JOB_TITLE_PROPERTY).asText());
			}
			if (requestNode.get(JOB_DESCRIPTION_PROPERTY) != null) {
				job.setDescription(requestNode.get(JOB_DESCRIPTION_PROPERTY).asText());
			}

			if (requestNode.get(JOB_PHONE_NUMBER_PROPERTY) != null) {
				job.setPhoneNumber(requestNode.get(JOB_PHONE_NUMBER_PROPERTY).asText());
			}
			if (requestNode.get(JOB_SUBCATEGORY_ID_PROPERTY) != null) {
				Long jobSubCategoryId = requestNode.get(JOB_SUBCATEGORY_ID_PROPERTY).asLong();
				job.setSubCategory(staticDataBusiness.getJobSubCategoryById(jobSubCategoryId));
			}
			if (requestNode.get(JOB_COUNTY_ID_PROPERTY) != null) {
				Long jobCountyId = requestNode.get(JOB_COUNTY_ID_PROPERTY).asLong();
				job.setCounty(staticDataBusiness.getCountyById(jobCountyId));
			}
			if (requestNode.get(JOB_EMAIL_PROPERTY) != null) {
				String jobEmail = requestNode.get(JOB_EMAIL_PROPERTY).asText();
				new EmailValidator().validate(jobEmail);
				job.setEmail(jobEmail);
			}

			job.setTimeStamp(System.currentTimeMillis());
			jobBusiness.saveJob(job);

			LOGGER_API.info("response: update job - OK");
			return new ResponseEntity<String>(HttpStatus.OK);
		} catch (Exception e) {
			LOGGER_API.error("response: update job", e);
			return handleException(e);
		}
	}

	@Override
	protected Class<Job> getEntityClass() {
		return Job.class;
	}

}
